package com.ljk.studywebsocket.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.URI;
import java.security.Principal;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 基于springframework的websocket实现
 * websocket 消息处理类，类似于controller
 */
@Component
@Slf4j
public class DefaultHandler implements WebSocketHandler {

    private final Map<String, WebSocketSession> sessionMap = new ConcurrentHashMap<>();

    /**
     * 建立连接
     *
     * @param session 会话
     * @throws Exception 异常
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        log.info("客户端{}接入", session.getId());
        sendMessage(String.format("您已接入通讯,当前在线数:%d", sessionMap.size()+1), session);
        sendMessage("分配到的ID:" + session.getId(), session);
        sendAllMessage("检测到[" + session.getId() + "]已上线");
        sessionMap.put(session.getId(), session);
        printSession(session);
    }


    /**
     * 接收消息
     *
     * @param session 会话
     * @param message 消息
     * @throws Exception 异常
     */
    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        log.info("接收客户端消息:{}", message);
        // 接收消息
        String msg = String.format("[%s]说:%s", session.getId(), message.getPayload().toString());
        sendAllMessage(msg);
        printSession(session);
    }


    /**
     * 发生错误
     *
     * @param session   会话
     * @param throwable throwable
     * @throws Exception 异常
     */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable throwable) throws Exception {
        // 清除用户缓存信息
        log.error("连接{}报错,移除连接,错误信息:{}", session.getId(), throwable.getMessage());
        sessionMap.remove(session.getId());
    }

    /**
     * 关闭连接
     *
     * @param session     会话
     * @param closeStatus 关闭状态
     * @throws Exception 异常
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        // 清除用户缓存信息
        log.info("客户端{}关闭连接", session.getId());
        sessionMap.remove(session.getId());
        sendAllMessage("检测到[" + session.getId() + "]已下线,剩余在线数:" + sessionMap.size());
        try {
            session.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 是否支持发送部分消息
     *
     * @return true/false
     */
    @Override
    public boolean supportsPartialMessages() {
        return false;
    }

    /**
     * 自定义发送消息
     *
     * @param message  消息
     * @param username 用户名
     */
    public void sendMessage(String message, WebSocketSession session) {
        if (session == null || message == null) {
            return;
        }
        if (session.isOpen()) {
            try {
                session.sendMessage(new TextMessage(message));
            } catch (IOException ignore) {
            }
        }
    }

    private void sendAllMessage(String message) {
        sessionMap.forEach((k, v) -> {
            try {
                // 发送消息
                v.sendMessage(new TextMessage(message));
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }


    private String printSession(WebSocketSession session) {
        String id = session.getId();
        URI uri = session.getUri();
        HttpHeaders handshakeHeaders = session.getHandshakeHeaders();
        Map<String, Object> attributes = session.getAttributes();
        Principal principal = session.getPrincipal();
        InetSocketAddress localAddress = session.getLocalAddress();
        InetSocketAddress remoteAddress = session.getRemoteAddress();
        String acceptedProtocol = session.getAcceptedProtocol();
        int textMessageSizeLimit = session.getTextMessageSizeLimit();
        int binaryMessageSizeLimit = session.getBinaryMessageSizeLimit();
        List<WebSocketExtension> extensions = session.getExtensions();
        boolean isOpen = session.isOpen();
        return null;
    }
}

